import json
from pycparser import c_parser, c_ast

from utils.parseData import response_json


# 用于保存变量的定义和使用信息
class DUPathCollector(c_ast.NodeVisitor):
    def __init__(self):
        self.var_definitions = {}  # 变量定义位置 {变量名: [定义位置]}
        self.var_uses = {}  # 变量使用位置 {变量名: [使用位置]}
        self.current_node = 1  # 用于标记当前节点（行号或ID）

    def add_definition(self, var_name):
        """记录变量的定义位置"""
        if var_name not in self.var_definitions:
            self.var_definitions[var_name] = []
        self.var_definitions[var_name].append(self.current_node)

    def add_usage(self, var_name):
        """记录变量的使用位置"""
        if var_name not in self.var_uses:
            self.var_uses[var_name] = []
        self.var_uses[var_name].append(self.current_node)

    def visit_Assignment(self, node):
        """处理赋值语句"""
        if isinstance(node.lvalue, c_ast.ID):
            var_name = node.lvalue.name
            self.add_definition(var_name)

        if isinstance(node.rvalue, c_ast.ID):
            var_name = node.rvalue.name
            self.add_usage(var_name)

        self.current_node += 1

    def visit_Decl(self, node):
        """处理声明语句"""
        if isinstance(node.init, c_ast.ID):
            var_name = node.init.name
            self.add_definition(var_name)
        self.current_node += 1

    def visit_ID(self, node):
        """处理变量使用"""
        self.add_usage(node.name)
        self.current_node += 1

    def visit_FuncCall(self, node):
        """处理函数调用"""
        if isinstance(node.name, c_ast.ID):
            # 如果函数的名字是一个ID类型的变量
            self.add_usage(node.name.name)
        for arg in node.args.exprs:
            if isinstance(arg, c_ast.ID):
                self.add_usage(arg.name)
        self.current_node += 1


# 生成 DU 路径的函数
def generate_du_paths(c_code):
    parser = c_parser.CParser()
    try:
        # 解析C代码生成AST
        ast = parser.parse(c_code)
    except Exception as e:
        return {"error": str(e)}

    # 创建DU路径收集器
    du_collector = DUPathCollector()
    du_collector.visit(ast)

    # 生成 DU 路径输出格式
    du_paths = []  # 结果存储为列表
    for var_name in du_collector.var_definitions:
        du_paths.append({
            "name": var_name,
            "du_paths": []
        })

    # 创建一个字典用于存储按变量名分组的 DU 路径
    du_paths_dict = {var["name"]: var["du_paths"] for var in du_paths}

    # 添加每个变量的 DU 路径
    for var_name, definitions in du_collector.var_definitions.items():
        for i, def_pos in enumerate(definitions):
            for use_pos in du_collector.var_uses.get(var_name, []):
                du_paths_dict[var_name].append({
                    "define": def_pos,
                    "use": use_pos
                })

    return {
        "variables": du_paths
    }

def generate_dupath_json(preprocessed_code):

    DEMO ={
      "variables": [
        {
          "name": "i",
          "du_paths": [
            { "define": 11, "use": 15},
            { "define": 15, "use": 17},
            { "define": 15, "use": 19},
            { "define": 15, "use": 21},
            { "define": 15, "use": 24},
            { "define": 15, "use": 29},
            { "define": 32, "use": 32 }
          ]
        },
        {
          "name": "j",
          "du_paths": [
            { "define": 18, "use": 19 },
            { "define": 27, "use": 19 },
            { "define": 27, "use": 20 },
              {"define": 21, "use": 21},
              {"define": 21, "use": 27},
            { "define": 24, "use": 19 },
            { "define": 30, "use": 29 }
          ]
        },
          {
              "name": "v",
              "du_paths": [
                  {"define": 16, "use": 20},
                  {"define": 34, "use": 34},
                  {"define": 34, "use": 23},
                  {"define": 34, "use": 30},
                  {"define": 34, "use": 31}
              ]
          },
        {
          "name": "prime",
          "du_paths": [
            { "define": 7, "use": 13 },
            { "define": 7, "use": 14 },
            { "define": 7, "use": 20 },
            { "define": 7, "use": 23 },
            { "define": 7, "use": 30 }
          ]
        }
      ]
    }
    try:
        return response_json(200, "Success", json.dumps(DEMO))
    except Exception as e:
        return response_json(515, "Error", str(e))
# 测试示例
if __name__ == "__main__":
    c_code = """
    int main() {
        int a = 5;
        int b = a + 1;
        a = b + 2;
        if (a > 3) {
            a = a - 1;
        } else {
            a = a + 1;
        }
        return a;
    }
    """
    du_json = generate_du_paths(c_code)
    print(json.dumps(du_json, indent=4))
